define(["require", "exports"], function (require, exports) {
    "use strict";
    exports.__esModule = true;
    exports.OnceInitDestry = exports.onceLife = exports.getAsOne = exports.arrayInit = exports.orRun = exports.newLifeModel = exports.Watcher = exports.mve = exports.notEqualChange = exports.alawaysChange = void 0;
    var Dep = /** @class */ (function () {
        function Dep() {
            this.id = Dep.uid++;
            this.subs = {};
        }
        Dep.prototype.depend = function () {
            if (Dep.target) {
                this.subs[Dep.target.id] = Dep.target;
            }
        };
        Dep.prototype.notify = function () {
            var oldSubs = this.subs;
            this.subs = {};
            for (var key in oldSubs) {
                oldSubs[key].update();
            }
        };
        Dep.uid = 0;
        Dep.watcherCount = 0;
        return Dep;
    }());
    /**
     * 必须默认true，因为引用类似修改无法通过相等判断
     * @param a
     * @param b
     * @returns
     */
    var alawaysChange = function (a, b) {
        return true;
    };
    exports.alawaysChange = alawaysChange;
    /**
     * 不相同的时候
     * @param a
     * @param b
     * @returns
     */
    var notEqualChange = function (a, b) {
        return a != b;
    };
    exports.notEqualChange = notEqualChange;
    var mve;
    (function (mve) {
        function delaySetAfter(fun, after) {
            var newFun = fun;
            newFun.after = after;
            return newFun;
        }
        mve.delaySetAfter = delaySetAfter;
        function isDelaySet(v) {
            return !!(('after' in v) && v.after);
        }
        mve.isDelaySet = isDelaySet;
        function isGValueOrDelaySet(v) {
            return typeof (v) == 'function';
        }
        mve.isGValueOrDelaySet = isGValueOrDelaySet;
        /**新存储器*/
        function valueOf(v, shouldChange) {
            if (shouldChange === void 0) { shouldChange = exports.alawaysChange; }
            var dep = new Dep();
            return function () {
                if (arguments.length == 0) {
                    dep.depend();
                    return v;
                }
                else {
                    if (Dep.target) {
                        throw "计算期间不允许修改";
                    }
                    else {
                        var nv = arguments[0];
                        if (shouldChange(v, nv)) {
                            v = nv;
                            dep.notify();
                        }
                    }
                }
            };
        }
        mve.valueOf = valueOf;
        /**
         * 原子的值类型
         * @param v
         * @param shouldChange
         * @returns
         */
        function atomValueOf(v, shouldChange) {
            if (shouldChange === void 0) { shouldChange = exports.notEqualChange; }
            return valueOf(v, shouldChange);
        }
        mve.atomValueOf = atomValueOf;
        /**
         * 转化成统一的函数
         * @param a
         */
        function valueOrCall(a) {
            if (typeof (a) == 'function') {
                return a;
            }
            else {
                return function () { return a; };
            }
        }
        mve.valueOrCall = valueOrCall;
        /**
         * 重写属性值为可观察
         * @param a
         * @param fun
         */
        function reWriteMTValue(a, fun) {
            var after = a['after'];
            var vm = function () { return fun(a()); };
            vm.after = after;
            return vm;
        }
        mve.reWriteMTValue = reWriteMTValue;
        var ArrayModel = /** @class */ (function () {
            function ArrayModel(array) {
                this.array = array;
                this.views = [];
                this.size_value = mve.valueOf(0);
                this.size = this.size_value;
                //长度是可观察的
                this.reload_size();
                this.locked = false;
            }
            ArrayModel.prototype.lock = function () {
                if (this.locked) {
                    var msg = "\u671F\u95F4\u7981\u6B62\u64CD\u4F5C";
                    console.warn(msg, this);
                    throw new Error(msg);
                }
                this.locked = true;
            };
            ArrayModel.prototype.unlock = function () {
                if (this.locked) {
                    this.locked = false;
                }
                else {
                    var msg = "\u7981\u6B62\u91CD\u590D\u89E3\u9501";
                    console.warn(msg, this);
                    throw new Error(msg);
                }
            };
            /**
             * 检查下标
             * @param index 下标
             * @param isThrow 是否作为抛出
             * @param lessSize 必须小于size
             */
            ArrayModel.prototype.checkIndex = function (index, noThrow, lessSize) {
                if (lessSize === void 0) { lessSize = false; }
                var size = this.size();
                if (index < 0 || index > size || (lessSize && index == size)) {
                    if (noThrow) {
                        return false;
                    }
                    else {
                        var msg = "\u8D85\u51FA\u8FB9\u754C[0~" + (lessSize ? size - 1 : size) + "]";
                        console.warn(msg, this);
                        throw new Error(msg);
                    }
                }
                return true;
            };
            ////////////////////////////////////////////////////////////////////
            ArrayModel.prototype.reload_size = function () {
                this.size_value(this.array.size());
            };
            ArrayModel.of = function () {
                var vs = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    vs[_i] = arguments[_i];
                }
                return new ArrayModel(vs);
            };
            ArrayModel.from = function (vs, noClone) {
                vs = noClone ? vs : vs.slice(0);
                return new ArrayModel(vs);
            };
            ////////////////////////////////////////////////////////////////////
            ArrayModel.prototype.addView = function (view) {
                this.views.push(view);
                //自动初始化
                for (var i = 0; i < this.array.size(); i++) {
                    view.insert(i, this.array.get(i));
                }
            };
            ArrayModel.prototype.removeView = function (view) {
                mb.Array.removeWhere(this.views, function (v) { return v == view; });
            };
            ////////////////////////////////////////////////////////////////////
            ArrayModel.prototype.insert = function (index, row, noThrow) {
                if (this.checkIndex(index, noThrow)) {
                    this.lock();
                    this.array.insert(index, row);
                    this.reload_size();
                    this.views.forEach(function (view) {
                        view.insert(index, row);
                    });
                    this.unlock();
                    return true;
                }
                return false;
            };
            ArrayModel.prototype.remove = function (index, noThrow) {
                if (this.checkIndex(index, noThrow, true)) {
                    this.lock();
                    /*更常识的使用方法*/
                    var row = this.get(index);
                    this.array.remove(index);
                    this.reload_size();
                    this.views.forEach(function (view) {
                        view.remove(index);
                    });
                    this.unlock();
                    return row;
                }
            };
            ArrayModel.prototype.set = function (index, row, noThrow) {
                if (this.checkIndex(index, noThrow, true)) {
                    this.lock();
                    var oldRow = this.array.set(index, row);
                    this.reload_size();
                    this.views.forEach(function (view) {
                        view.set(index, row);
                    });
                    this.unlock();
                    return oldRow;
                }
            };
            ArrayModel.prototype.move = function (oldIndex, newIndex, noThrow) {
                if (this.checkIndex(oldIndex, noThrow, true) && this.checkIndex(newIndex, noThrow, true)) {
                    this.lock();
                    /**有效的方法*/
                    this.array.move(oldIndex, newIndex);
                    this.reload_size();
                    this.views.forEach(function (view) {
                        view.move(oldIndex, newIndex);
                    });
                    this.unlock();
                    return true;
                }
                return false;
            };
            /**清理匹配项 */
            ArrayModel.prototype.removeWhere = function (fun) {
                mb.Array.removeWhere(this, fun);
            };
            /**清理单纯相等的项 */
            ArrayModel.prototype.removeEqual = function (row) {
                this.removeWhere(function (theRow) { return theRow == row; });
            };
            /*多控件用array和model，单控件用包装*/
            ArrayModel.prototype.moveToFirst = function (index) {
                this.move(index, 0);
            };
            ArrayModel.prototype.moveToLast = function (index) {
                this.move(index, this.size() - 1);
            };
            ArrayModel.prototype.shift = function () {
                return this.remove(0);
            };
            ArrayModel.prototype.unshift = function (row) {
                return this.insert(0, row);
            };
            ArrayModel.prototype.pop = function () {
                return this.remove(this.size() - 1);
            };
            ArrayModel.prototype.push = function (row) {
                return this.insert(this.size(), row);
            };
            ArrayModel.prototype.clear = function () {
                while (this.size() > 0) {
                    this.pop();
                }
            };
            ArrayModel.prototype.reset = function (array) {
                if (array === void 0) { array = []; }
                this.clear();
                for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {
                    var row = array_1[_i];
                    this.push(row);
                }
            };
            //////////////////////////////////////////////////////////////////////////////
            ArrayModel.prototype.get = function (i, noThrow) {
                if (this.checkIndex(i, noThrow, true)) {
                    //不支持响应式
                    return this.array.get(i);
                }
            };
            ArrayModel.prototype.getLast = function (noThrow) {
                return this.get(this.array.size() - 1, noThrow);
            };
            ArrayModel.prototype.findIndex = function (fun, from) {
                var size = this.size();
                for (var i = from || 0; i < size; i++) {
                    var row = this.get(i);
                    if (fun(row, i)) {
                        return i;
                    }
                }
                return -1;
            };
            ArrayModel.prototype.forEach = function (fun) {
                var size = this.size();
                for (var i = 0; i < size; i++) {
                    fun(this.get(i), i);
                }
            };
            ArrayModel.prototype.map = function (fun) {
                var vs = [];
                var size = this.size();
                for (var i = 0; i < size; i++) {
                    vs.push(fun(this.get(i), i));
                }
                return vs;
            };
            ArrayModel.prototype.filter = function (fun) {
                var vs = [];
                var size = this.size();
                for (var i = 0; i < size; i++) {
                    var row = this.get(i);
                    if (fun(row, i)) {
                        vs.push(row);
                    }
                }
                return vs;
            };
            ArrayModel.prototype.findRow = function (fun, from) {
                var size = this.size();
                for (var i = from || 0; i < size; i++) {
                    var row = this.get(i);
                    if (fun(row, i)) {
                        return row;
                    }
                }
            };
            ArrayModel.prototype.indexOf = function (row, from) {
                return this.findIndex(function (theRow) { return theRow == row; }, from);
            };
            ArrayModel.prototype.count = function (fun) {
                var size = this.size();
                var count = 0;
                for (var i = 0; i < size; i++) {
                    var row = this.get(i);
                    if (fun(row, i)) {
                        count++;
                    }
                }
                return count;
            };
            ArrayModel.prototype.exist = function (fun) {
                var size = this.size();
                for (var i = 0; i < size; i++) {
                    var row = this.get(i);
                    if (fun(row, i)) {
                        return true;
                    }
                }
                return false;
            };
            ArrayModel.prototype.all = function (fun) {
                var size = this.size();
                for (var i = 0; i < size; i++) {
                    var row = this.get(i);
                    if (!fun(row, i)) {
                        return false;
                    }
                }
                return true;
            };
            ArrayModel.prototype.join = function (split) {
                return this.map(function (v) { return v; }).join(split);
            };
            return ArrayModel;
        }());
        mve.ArrayModel = ArrayModel;
        /**
         * @deprecated 使用ArrayModel.of
         * @param array
         * @returns
         */
        function arrayModelOf(array, noClone) {
            return ArrayModel.from(array, noClone);
        }
        mve.arrayModelOf = arrayModelOf;
    })(mve = exports.mve || (exports.mve = {}));
    /////////////////////////////////////////////////////////////////////////////////////////////////////////
    var Watcher = /** @class */ (function () {
        function Watcher(realUpdate) {
            this.realUpdate = realUpdate;
            this.id = Watcher.uid++;
            this.enable = true;
            Dep.watcherCount++;
            this.update();
        }
        Watcher.prototype.update = function () {
            if (this.enable) {
                this.realUpdate(this);
            }
        };
        Watcher.prototype.disable = function () {
            this.enable = false;
            Dep.watcherCount--;
        };
        Watcher.of = function (exp) {
            return new Watcher(function (it) {
                Dep.target = it;
                exp();
                Dep.target = null;
            });
        };
        Watcher.ofExp = function (before, exp, after) {
            return new Watcher(function (it) {
                var a = before();
                Dep.target = it;
                var b = exp(a);
                Dep.target = null;
                after(b);
            });
        };
        Watcher.ofBefore = function (before, exp) {
            return new Watcher(function (it) {
                var a = before();
                Dep.target = it;
                exp(a);
                Dep.target = null;
            });
        };
        Watcher.ofAfter = function (exp, after) {
            return new Watcher(function (it) {
                Dep.target = it;
                var b = exp();
                Dep.target = null;
                after(b);
            });
        };
        Watcher.uid = 0;
        return Watcher;
    }());
    exports.Watcher = Watcher;
    var LifeModelImpl = /** @class */ (function () {
        function LifeModelImpl() {
            this.destroyList = [];
            this.pool = [];
        }
        LifeModelImpl.prototype.Watch = function (exp) {
            this.pool.push(Watcher.of(exp));
        };
        LifeModelImpl.prototype.WatchExp = function (before, exp, after) {
            this.pool.push(Watcher.ofExp(before, exp, after));
        };
        LifeModelImpl.prototype.WatchBefore = function (before, exp) {
            this.pool.push(Watcher.ofBefore(before, exp));
        };
        LifeModelImpl.prototype.WatchAfter = function (exp, after) {
            this.pool.push(Watcher.ofAfter(exp, after));
        };
        LifeModelImpl.prototype.Cache = function (fun, shouldChange) {
            if (shouldChange === void 0) { shouldChange = exports.alawaysChange; }
            var dep = new Dep();
            var cache;
            this.Watch(function () {
                var nv = fun();
                if (shouldChange(cache, nv)) {
                    cache = nv;
                    dep.notify();
                }
            });
            return function () {
                dep.depend();
                return cache;
            };
        };
        LifeModelImpl.prototype.AtomCache = function (fun, shouldChange) {
            if (shouldChange === void 0) { shouldChange = exports.notEqualChange; }
            return this.Cache(fun, shouldChange);
        };
        LifeModelImpl.prototype.destroy = function () {
            while (this.pool.length > 0) {
                this.pool.pop().disable();
            }
            for (var _i = 0, _a = this.destroyList; _i < _a.length; _i++) {
                var destroy = _a[_i];
                destroy();
            }
        };
        return LifeModelImpl;
    }());
    function newLifeModel() {
        var lm = new LifeModelImpl();
        return {
            me: lm,
            destroy: function () {
                lm.destroy();
            }
        };
    }
    exports.newLifeModel = newLifeModel;
    function orRun(v, def) {
        if (v) {
            return v();
        }
        return def;
    }
    exports.orRun = orRun;
    /**
     * 列表初始化
     * @param vs
     * @param initV
     * @returns
     */
    function arrayInit(vs, initV) {
        var size = vs.length;
        var destroys = [];
        for (var i = 0; i < size; i++) {
            var destroy = initV(vs[i]);
            if (destroy) {
                destroys.unshift(destroy);
            }
        }
        //返回销毁函数
        var dsize = destroys.length;
        if (dsize > 1) {
            return function () {
                for (var i = 0; i < dsize; i++) {
                    destroys[i]();
                }
            };
        }
        else if (dsize == 1) {
            return destroys[0];
        }
    }
    exports.arrayInit = arrayInit;
    /**
     * 整合成一个初始化函数
     * @param inits
     * @returns
     */
    function getAsOne(inits) {
        var size = inits.length;
        if (size > 1) {
            return function () {
                return arrayInit(inits, mb);
            };
        }
        else if (size == 1) {
            return inits[0];
        }
    }
    exports.getAsOne = getAsOne;
    /**
     * 一次生活
     * @param init
     * @param nowarn
     * @returns
     */
    function onceLife(init, nowarn) {
        var warn = !nowarn;
        var self = {
            isInit: false,
            isDestroy: false,
            init: function () {
                if (self.isInit) {
                    if (warn) {
                        console.warn("禁止重复init");
                    }
                }
                else {
                    self.isInit = true;
                    return init();
                }
            }
        };
        return self;
    }
    exports.onceLife = onceLife;
    var OnceInitDestry = /** @class */ (function () {
        function OnceInitDestry() {
            this.inited = false;
            this.destroyed = false;
        }
        OnceInitDestry.prototype.init = function () {
            if (this.inited) {
                throw "\u7981\u6B62\u91CD\u590D\u521D\u59CB\u5316";
            }
            this.inited = true;
        };
        OnceInitDestry.prototype.destroy = function () {
            if (!this.inited) {
                throw "\u7981\u6B62\u672A\u521D\u59CB\u5316\u9500\u6BC1";
            }
            if (this.destroyed) {
                throw "\u5DF2\u7ECF\u9500\u6BC1\u7981\u6B62\u91CD\u590D\u64CD\u4F5C";
            }
            this.destroyed = true;
        };
        return OnceInitDestry;
    }());
    exports.OnceInitDestry = OnceInitDestry;
});
